package com.sbio.udiapp.ui;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableList;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;

import com.alibaba.fastjson.JSONObject;
import com.blankj.utilcode.util.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sbio.udiapp.BuildConfig;
import com.sbio.udiapp.adapter.OutStockApplyAdapter;
import com.sbio.udiapp.adapter.StockAdapter;
import com.sbio.udiapp.common.bean.OutStockApply;
import com.sbio.udiapp.common.bean.RequestUniParam;
import com.sbio.udiapp.common.bean.Stock;
import com.sbio.udiapp.databinding.ActivityMisdeliveryNoticeBinding;
import com.sbio.udiapp.listener.ListAdapterListener;
import com.sbio.udiapp.net.api.ApiService;
import com.sbio.udiapp.net.bean.AjaxResult;
import com.sbio.udiapp.util.ApiServiceUtil;
import com.sbio.udiapp.util.DialogUtil;
import com.sbio.udiapp.util.IntentUtil;
import com.sbio.udiapp.util.JsonUtil;
import com.sbio.udiapp.util.LogUtil;
import com.sbio.udiapp.util.SharedPreferencesUtil;
import com.sbio.udiapp.util.ToastUtil;
import com.sbio.udiapp.util.VibratorUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

import javax.inject.Inject;

import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

@AndroidEntryPoint
public class MisdeliveryNoticeActivity extends AppCompatActivity implements ListAdapterListener {
    @Inject
    ApiService apiService;



    ActivityMisdeliveryNoticeBinding binding;

    List<Stock> stockList;

    OutStockApply outStockApply;


    /**
     * 用于上传时的数据
     */
    OutStockApply outStockApplyCopy;

    ObservableList<String> nos = new ObservableArrayList<>();

    BroadcastReceiver broadcastReceiver;

    private IntentFilter intentFilter;

    OutStockApplyAdapter adapter;

    ProgressDialog progressDialog;

    AtomicInteger progressCount = new AtomicInteger();

    boolean saveOutStockApplyFlag = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMisdeliveryNoticeBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        //初始化偏好
        SharedPreferencesUtil.init(this);
        //初始化进度条
        initProgressDialog();

        outStockApply = new OutStockApply();
        outStockApply.setNos(nos);
        //初始化页面扫码监听
        initSystemScanData();

        //初始化nos listView布局
        binding.nos.setLayoutManager(new LinearLayoutManager(this));
        adapter = new OutStockApplyAdapter(nos,this);
        binding.nos.setAdapter(adapter);

        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
//        dividerItemDecoration.setDrawable(ContextCompat.getDrawable(this, R.drawable.custom_divider)); // 设置自定义分割线样式
        binding.nos.addItemDecoration(dividerItemDecoration);
        binding.nos.setItemAnimator(new DefaultItemAnimator());
        //添加nos数据监听器
        addListener4nos();

        binding.toggleData.setOnClickListener(v -> {
            String pageNo = binding.pageNoEdit.getText().toString();
            String requestUniParam = RequestUniParam.create(String.format("点击了切换数据按钮，切换前pageNo:%s，切换到：%s", outStockApply.getPageNo(), pageNo)).toJson();
            showProcess();

            ApiServiceUtil.enqueue(() -> apiService.getOutStockApply(pageNo, requestUniParam), new Callback<AjaxResult>() {
                @Override
                public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                    hideProcess();
                    AjaxResult ajaxResult = response.body();
                    if (ajaxResult.isSuccess()) {
                        JSONObject result = ajaxResult.getData(JSONObject.class);
                        if (!StringUtils.isEmpty(result.getString("downStreamBillNo"))) {
                            VibratorUtil.vibrator();
                            ToastUtil.show("已经下推的单据不能拉取，页面编码已重置");
                            binding.pageNoEdit.setText(outStockApply.getPageNo());
                            return;
                        }
                        JSONObject data = result.getJSONObject("data");
                        //填充数据,不弹框
                        binding.searchStock.dismissDropDown();
                        binding.searchStock.setText(data.getString("stockNo"));
                        binding.searchStock.setListSelection(-1);
                        //暂时屏蔽同步
                        saveOutStockApplyFlag = false;
                        nos.clear();
                        nos.addAll(data.getObject("nos", List.class));
                        binding.productCount.setText(String.format("产品数量：%s", data.getInteger("udiCount")));
                        saveOutStockApplyFlag = true;
                        //修改pageNo
                        outStockApply.setPageNo(pageNo);
                        ToastUtil.show("切换成功");
                    } else {
                        ToastUtil.show(ajaxResult.getMsg()+"，页面编码已重置");
                        binding.pageNoEdit.setText(outStockApply.getPageNo());
                    }
                }

                @Override
                public void onFailure(Call<AjaxResult> call, Throwable t) {
                    hideProcess();
//                    ToastUtil.show("切换数据失败，请稍后尝试");

                    DialogUtil.showCommonAlertDialog(t.getMessage());
                    binding.pageNoEdit.setText(outStockApply.getPageNo());
                }
            });
        });


        //从服务端初始化页面编码
        initPageNo();
        //从服务端初始化仓库适配器
        initStockAdapter();
        //绑定提交业务
        binding.submit.setOnClickListener(v -> {
            String requestUniParam = RequestUniParam.create("点击了提交按钮").toJson();
            showProcess();
            ApiServiceUtil.enqueue(() -> apiService.pushBill(outStockApply.getPageNo(),requestUniParam,1), new Callback<AjaxResult>() {
                @Override
                public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                    hideProcess();
                    AjaxResult ajaxResult = response.body();
                    if (ajaxResult.isSuccess()) {
                        ToastUtil.show("下推成功");
                        MisdeliveryNoticeActivity.this.reset();
                    } else {
                        DialogUtil.showCommonAlertDialog("下推失败" + ajaxResult.getMsg());
                    }
                }

                @Override
                public void onFailure(Call<AjaxResult> call, Throwable t) {
                    hideProcess();
                    DialogUtil.showCommonAlertDialog(t.getMessage());

                }
            });
        });


    }



    private void initTestData() {
        List<String> data = new ArrayList<>();
//        for (int i = 0; i < 20; i++) {
//            data.add("0106973342001025\n" +
//                    "11240105\n" +
//                    "17260104\n" +
//                    "10T202401006\n" +
//                    "2100000140" + StringUtils.format("%02d", i));
//        }
        data.add("CKSQD051481");
        data.add("CKSQD051686");
//        data.add(formatUdi("0106973342000271112401121726011110T202401010210000000874"));
//        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001740"));
//        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001747"));
//        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001748"));
//        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001636"));
//        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001749"));
        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001744"));
        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001742"));
        data.add(formatUdi("0106973342000028112403121725031110T202403001210000001635"));

        new Handler().postDelayed(() -> nos.addAll(data), 200L);

    }

    /**
     * 程序进入前台的生命周期
     */
    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    protected void onPostResume() {
        super.onPostResume();

    }

    /**
     * 初始化进度条
     */
    private void initProgressDialog() {
        progressDialog = new ProgressDialog(MisdeliveryNoticeActivity.this);
        progressDialog.setMessage("加载中..."); // 设置提示信息
        progressDialog.setCancelable(true); // 设置是否允许用户通过点击屏幕或按返回键取消对话框
        progressDialog.show(); // 显示对话框
    }

    private void showProcess() {
        progressCount.incrementAndGet();
        progressDialog.show();
    }

    private void hideProcess(){
        int count = progressCount.decrementAndGet();
        if (count<=0) {
            progressDialog.hide();
        }
    }

    private void initPageNo() {
        showProcess();
        String requestUniParam = RequestUniParam.create("初始化页面编码").toJson();
        apiService.getNextPageNo(requestUniParam).enqueue(new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                hideProcess();
                if (response.code() != 200) {
                    ToastUtil.show("获取页面编码失败,请退出页面重试");
                    return;
                }
                AjaxResult result = response.body();
                if (result.isSuccess()) {
                    String pageNo = result.getData(String.class);
                    binding.pageNoEdit.setText(pageNo);
                    outStockApply.setPageNo(pageNo);
                    LogUtil.file("获取页面编码","pageNo:" + pageNo);
                }
                //初始化测试数据
                if (BuildConfig.DEBUG) {
//                    initTestData();
                }
            }

            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
//                ToastUtil.show("获取页面编码失败,请退出页面重试");
                DialogUtil.showCommonAlertDialog(t.getMessage());
            }
        });
    }

    //添加nos数据监听器
    private void addListener4nos() {
        nos.addOnListChangedCallback(new ObservableList.OnListChangedCallback<ObservableList<String>>() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onChanged(ObservableList<String> sender) {
                adapter.notifyDataSetChanged(); // 数据变化时通知适配器刷新列表
            }

            @Override
            public void onItemRangeChanged(ObservableList<String> sender, int positionStart, int itemCount) {
                adapter.notifyItemRangeChanged(positionStart, itemCount); // 通知适配器局部刷新
            }

            @Override
            public void onItemRangeInserted(ObservableList<String> sender, int positionStart, int itemCount) {
//                adapter.notifyItemRangeChanged(positionStart-1, itemCount); // 通知适配器局部刷新
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onItemRangeMoved(ObservableList<String> sender, int fromPosition, int toPosition, int itemCount) {
                adapter.notifyItemRangeRemoved(fromPosition, itemCount); // 通知适配器局部刷新
            }

            @Override
            public void onItemRangeRemoved(ObservableList<String> sender, int positionStart, int itemCount) {
                adapter.notifyItemRangeRemoved(positionStart, itemCount); // 通知适配器局部刷新
            }
        });
    }

    private void initStockAdapter() {
        showProcess();
        Call<AjaxResult> stockListCall = apiService.getStockList("");

        stockListCall.enqueue(new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {

                hideProcess();
                if (response.code() != 200) {
                    ToastUtil.show("获取仓库失败，请重新进入页面");
                    return;
                }
                stockList = response.body().getDataList(Stock.class);

                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    stockList = objectMapper.readValue(JsonUtil.toJsonString(response.body().getData()), new TypeReference<List<Stock>>() {
                    });
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }

                StockAdapter stockAdapter = new StockAdapter(MisdeliveryNoticeActivity.this, stockList);


                binding.searchStock.setAdapter(stockAdapter);
                binding.searchStock.setThreshold(1);
                String stockNo = SharedPreferencesUtil.getString("stockNo");
                if (stockNo != null) {
                    binding.searchStock.setText(stockNo);
                    outStockApply.setStockNo(stockNo);
                }


                binding.searchStock.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        Stock stock = stockAdapter.getItem(position);
                        if (stock != null) {
                            outStockApplyCopy = JsonUtil.copy(outStockApply,OutStockApply.class);
                            outStockApplyCopy.setStockNo(stock.getId());
                            saveOutStockApply2(()->{
                                outStockApply.setStockNo(stock.getId());
//                                binding.searchStock.setThreshold(1);
//                                binding.searchStock.setText(stock.getId());
                                binding.searchStock.setThreshold(100);
                                binding.searchStock.setText(stock.getId());
                                binding.searchStock.setThreshold(1);


                                //存储 stockNo，默认带出
                                SharedPreferencesUtil.saveString("stockNo", stock.getId());
                            },null);

                        }
                    }
                });
            }


            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
                DialogUtil.showCommonAlertDialog(t.getMessage());
            }
        });
    }


    public void initSystemScanData() {

        // 新建一个广播接收对象，实现数据接收和处理
        broadcastReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                try {
                    String action = intent.getAction();
                    if (action == null) {
                        return;
                    }
                    String data = IntentUtil.getStringExtra(intent);

                    switch (action) {
                        case IntentUtil.INTENT_ACTIONS_DEFAULT_1:
                        case IntentUtil.INTENT_ACTIONS_DEFAULT_2:
                            onBroadcastReceiver(data);
                        default:
                            break;
                    }
                } catch (Exception e) {
                    DialogUtil.showCommonAlertDialog(e.getMessage());
                }
            }

            private void onBroadcastReceiver(String barcodeData) {
                LogUtil.file("接收到广播数据", barcodeData);
                if (nos.contains(barcodeData)) {
                    ToastUtil.showError("数据重复");
                    return;
                }
                //如果是出库申请开头的数据那么就是outStockApplyNos
                if (barcodeData.indexOf("CKSQ") == 0) {
                    outStockApplyCopy = outStockApply.copy();
                    outStockApplyCopy.getNos().add(barcodeData);
                    saveOutStockApply2(()->nos.add(barcodeData),null);
                } else if (barcodeData.indexOf("XM") == 0) {
                    //箱码数据
                    outStockApplyCopy = outStockApply.copy();
                    outStockApplyCopy.getNos().add(barcodeData);
                    saveOutStockApply2(()->nos.add(barcodeData),null);
                } else if (barcodeData.indexOf("01") == 0 && barcodeData.length() == 56) {
                    String data = formatUdi(barcodeData);
                    outStockApplyCopy = outStockApply.copy();
                    outStockApplyCopy.getNos().add(barcodeData);
                    saveOutStockApply2(()->nos.add(barcodeData),null);
                } else {
                    //非法数据
                    ToastUtil.showError("非法数据，请检查");
                    return;
                }

//                saveOutStockApply();

            }
        };


        intentFilter = new IntentFilter();
        intentFilter.addAction(IntentUtil.INTENT_ACTIONS_DEFAULT_1);
        intentFilter.addAction(IntentUtil.INTENT_ACTIONS_DEFAULT_2);
    }

    @NonNull
    private static String formatUdi(String barcodeData) {
        /*StringBuilder sb = new StringBuilder(barcodeData);
        int[] positions = {16, 25, 34, 47};
        for (int position : positions) {
            sb.insert(position, "\n");
        }
        //箱码数据
        String data = sb.toString();
        return data;*/
        return barcodeData;
    }


    /**
     * 保存页面数据
     */
    private void saveOutStockApply2(Runnable r1,Runnable r2) {
        if (!saveOutStockApplyFlag) {
            return;
        }
        String requestUniParam = RequestUniParam.create("保存页面数据").toJson();
        showProcess();

        ApiServiceUtil.enqueue(() -> apiService.saveOutStockApply(outStockApplyCopy, requestUniParam), new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                hideProcess();
                AjaxResult ajaxResult = response.body();
                if (Objects.requireNonNull(ajaxResult).isSuccess()) {

                    String count = ajaxResult.getData(String.class);
                    binding.productCount.setText(String.format("产品数量：%s", count));
                    ToastUtil.showSuccess("保存成功");
                    Optional.ofNullable(r1).ifPresent(Runnable::run);
                } else {
                    Optional.ofNullable(r2).ifPresent(Runnable::run);
                    DialogUtil.showCommonAlertDialog(ajaxResult.getMsg());
                }
            }

            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
                Optional.ofNullable(r2).ifPresent(Runnable::run);
                DialogUtil.showCommonAlertDialog(t.getMessage());
            }
        });
    }

    @Override
    public void remove(String datum) {
        outStockApplyCopy = outStockApply.copy();
        outStockApplyCopy.getNos().remove(datum);
        saveOutStockApply2(()->{
            nos.remove(datum);

        }, null);
    }

    public void reset() {
        showProcess();
        nos.clear();
        outStockApply = new OutStockApply();
        outStockApply.setNos(nos);
        initPageNo();
        String stockNo = SharedPreferencesUtil.getString("stockNo");
        if (stockNo != null) {
            binding.searchStock.setText(stockNo);
            outStockApply.setStockNo(stockNo);
        }
        binding.productCount.setText(String.format("产品数量：%s", ""));
        hideProcess();
    }

    @Override
    protected void onPause() {
        if (broadcastReceiver != null) {
            unregisterReceiver(broadcastReceiver); // 取消广播注册
        }
        super.onPause();
    }
}